using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using data.contracts;
using Microsoft.Msagl.Drawing;
using modelbuilder.parser.pins;

namespace ebc.viz.modelrenderer
{
    public class Render_boards : ebc.viz.contracts.IRender_boards
    {
        private readonly EbcPinParser _pinParser = new EbcPinParser();


        public void Process(IEnumerable<Board> boards)
        {
            Trace.TraceInformation("Render boards {0}", string.Join(",", boards.Select(b => b.Name)));
            this.Graphs(boards.Select(Render_board).ToArray());
        }


        private Graph Render_board(Board board)
        {
            var graph = new Graph(board.Name);
            foreach (var wire in board.Wires)
            {
                var edge = CreateFlowEdge(graph, wire);
                ColorNode(edge.SourceNode);
                ColorNode(edge.TargetNode);
            }
            foreach (var dependency in board.Dependencies) {
                var edge = CreateDependencyEdge(graph, dependency);
                ColorNode(edge.SourceNode);
                ColorNode(edge.TargetNode);
            }
            return graph;
        }

        private Edge CreateFlowEdge(Graph graph, Wire wire)
        {
            string toPinPartname="?" + wire.To, fromPinPartname="?" + wire.From;

            try
            {
                toPinPartname = _pinParser.Parse(wire.To).First().Board;
            }
            catch (Exception ex)
            {
                Trace.TraceError("Parsing of to-pin failed: {0}", wire.To);
            }
            toPinPartname = Name_this_correctly_in_to_pin(toPinPartname);

            try
            {
                fromPinPartname = _pinParser.Parse(wire.From).First().Board;
            }
            catch (Exception ex)
            {
                Trace.TraceError("Parsing of from-pin failed: {0}", wire.From);
            }

            var edge = graph.AddEdge(fromPinPartname, wire.Type, toPinPartname);
            if (edge.Label != null)
            {
                edge.Label.FontSize = 6;
                edge.Label.FontColor = Color.DarkGray;
            }
            return edge;
        }

        private Edge CreateDependencyEdge(Graph graph, Dependency dependency)
        {
            string toPinPartname = dependency.Type;
            string fromPinPartname = "";

            try
            {
                fromPinPartname = _pinParser.Parse(dependency.Dependent).First().Board;
            }
            catch (Exception ex)
            {
                Trace.TraceError("Parsing of from-pin failed: {0}", dependency.Dependent);
            }

            var edge = graph.AddEdge(fromPinPartname, "abh.", toPinPartname);
            if (edge.Label != null)
            {
                edge.Label.FontSize = 6;
                edge.Label.FontColor = Color.DarkGray;
                edge.Attr.AddStyle(Style.Dotted);
            }
            return edge;
        }

        private string Name_this_correctly_in_to_pin(string toPinPartname)
        {
            return toPinPartname == "this" ? "~this" : toPinPartname;
        }

        private void ColorNode(Node node)
        {
            node.Label.FontSize = 9;
            if (node.LabelText == "this" || node.LabelText == "~this")
            {
                node.LabelText = "";
                node.Attr.Color = Color.LightGray;
                node.Attr.Shape = Shape.Circle;
            }
        }


        public event Action<Graph[]> Graphs;
    }
}